#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdlib.h>
#include <arpa/inet.h>

typedef int bool;
#define false 0
#define true 1

bool parse(char *command, char **args);
bool mapCommands(char **args);
void execute(char **args, const bool runInBG);

char ls[] = "ls";
char pwd[] = "pwd";
char cp[] = "cp";
char mv[] = "mv";
char rm[] = "rm";
char emacs[] = "emacs";
char cat[] = "cat";

int main () {

    bool quit = false;
    
    while(!quit){
        char command[80];
        
        printf("dos > ");
        fgets(command, sizeof(command), stdin);
        
        char *args[80];
        bool runInBG = parse(command, args);
        
        if(mapCommands(args)){
            if(strcmp(*args, "quit") != 0){
                execute(args, runInBG);
            } else {
                quit = true;
            }
        } else {
            printf("Invalid command: %s\n", *args);
        }
    }
    return 0;
}

bool parse(char *command, char **args){
    bool runInBG = false;
    
    while(*command != '\0'){
        if(*command == ' ' || *command == '\t' || *command == '\n'){
            *command++ = '\0';
        }else if(*command == '&'){
            *command++ = '\0';
            runInBG = true;
            break;
        }else{
            *args++ = command;
            while(*command != ' ' && *command != '\n' && *command != '\0'){
                command++;
            }
        }
    }
    
    return runInBG;
}

bool mapCommands(char **args){
    if(strcmp(*args, "dir") == 0){
        *args = ls;
    } else if(strcmp(*args, "whereami") == 0){
        *args = pwd;
    } else if(strcmp(*args, "copy") == 0){
        *args = cp;
    } else if(strcmp(*args, "rename") == 0){
        *args = mv;
    } else if(strcmp(*args, "delete") == 0){
        *args = rm;
    } else if(strcmp(*args, "edit") == 0){
        *args = emacs;
    } else if(strcmp(*args, "type") == 0){
        *args = cat;
    } else if(strcmp(*args, "quit") == 0){
        //leave as is
    } else {
        return false;
    }
    return true;
}

void execute(char **args, const bool runInBG){
    pid_t pid = fork();
    
    if(pid == 0){
       if(execvp(*args, args) < 0){
           puts("ERROR");
           exit(1);
       }
   } else {
       waitpid(pid, NULL, 0);
   }
}
